﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using DNNEventLogViewer.Properties;

namespace DNNEventLogViewer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        


        private void Form1_Load(object sender, EventArgs e)
        {
            if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
            {
                this.Text += @" "+ System.Deployment.Application.ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();
            } else
            {
                this.Text += @" " + System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString();
            }

            ContextMenuStrip mnu = new ContextMenuStrip();
            ToolStripMenuItem mnuCopy = new ToolStripMenuItem("Copy Value");
            ToolStripMenuItem mnuCut = new ToolStripMenuItem("Cut");
            ToolStripMenuItem mnuPaste = new ToolStripMenuItem("Paste");
            //Assign event handlers
            mnuCopy.Click += new EventHandler(mnuCopy_Click);
            //mnuCut.Click += new EventHandler(mnuCut_Click);
            //mnuPaste.Click += new EventHandler(mnuPaste_Click);
            //Add to main context menu
            mnu.Items.AddRange(new ToolStripItem[] { mnuCopy});
            //Assign to datagridview
            listView1.ContextMenuStrip = mnu;
            
            // create browser control for message
            XmlBrowser mBrowser = new XmlBrowser();
            mBrowser.Name = "MsgBrowser";
            mBrowser.Dock = DockStyle.Fill;
            tabPage2.Controls.Add(mBrowser);

            // create browser control for xml
            XmlBrowser xBrowser = new XmlBrowser();
            xBrowser.Name = "XmlBrowser";
            xBrowser.Dock = DockStyle.Fill;
            tabPage3.Controls.Add(xBrowser);

            FormatLegendPanel();
            LoadConnectionStrings();

        }

        private void SaveConnectionStrings()
        {
            if (!Settings.Default.dbConnectionList.Contains(comboBox1.Text))
            {
                Settings.Default.dbConnectionList.Add(comboBox1.Text);
                comboBox1.Items.Add(comboBox1.Text);
            }
            Settings.Default.Save();

        }

        private void LoadConnectionStrings()
        {
            comboBox1.Items.Clear();
            foreach(var c in Settings.Default.dbConnectionList)
            {
                comboBox1.Items.Add(c);
            }

            comboBox1.Text = comboBox1.Items[comboBox1.Items.Count - 1].ToString();

        }

        private void FormatLegendPanel()
        {
            // color legend
            lblException.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.Exception));


            lblSecurityException.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.SecurityException));

            lblGeneralAdmin.BackColor =
            System.Drawing.ColorTranslator.FromHtml(
                DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.GeneralAdminOperation));

            lblAdminAlert.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.AdminAlert));

            lblHostAlert.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.HostAlert));


            lblDeleted.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.ItemDeleted));


            lblItemCreated.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.ItemCreated));
            lblItemUpdated.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.ItemUpdated));



            lblOpFailed.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.OperationFailure));

            lblOpSuccess.BackColor =
                System.Drawing.ColorTranslator.FromHtml(
                    DNNEventLogTypes.GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.OperationSuccess));

            
        }

        protected void mnuCopy_Click(object sender, EventArgs e)
        {

            MessageBox.Show("NOT Implemented");
            return;
            Clipboard.SetData(DataFormats.Text, listView1.SelectedItems[0].Text);
        }

        /// <summary>
        /// Is sql query a select based command (ie no update/delete/drop/modify etc)
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        private bool IsSelectCommand(string sql)
        {
            if (sql.TrimStart().ToLower().StartsWith("select"))
                return true;

            return false;
        }


        private void button1_Click(object sender, EventArgs e)
        {
            if (!IsSelectCommand(txtQuery.Text))
            {
                MessageBox.Show("Can only use SELECT command");
                return;
            }

            btnExecuteQuery.Enabled = false;
            dataGridView1.Enabled = false;

            try
            {
                SqlConnection sqlC = new SqlConnection(comboBox1.Text);
                SqlDataAdapter dataAdapter = new SqlDataAdapter(txtQuery.Text, sqlC);
                SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);

                DataTable table = new DataTable
                                      {
                                          Locale = System.Globalization.CultureInfo.InvariantCulture
                                      };
                dataAdapter.Fill(table);
                BindingSource dbBindSource = new BindingSource();
                dbBindSource.DataSource = table;
                dataGridView1.ReadOnly = true;
                dataGridView1.DataSource = dbBindSource;
                dataGridView1.Enabled = true;

                SaveConnectionStrings();
            } catch (SqlException sEx)
            {
                MessageBox.Show(sEx.Message);
            }

            btnExecuteQuery.Enabled = true;
        }


        /// <summary>
        /// Return Columns Data as String
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <param name="columnName"></param>
        private string GetDataGridColumnValueAsString(int rowIndex, string columnName)
        {
            if (dataGridView1.Columns.Contains(columnName))
            {
                return dataGridView1.Rows[rowIndex].Cells[columnName].Value as string;
            }

            return string.Empty;
        }


        private void dataGridView1_SelectionChanged(object sender, EventArgs e)
        {
            if (dataGridView1.SelectedRows.Count>0)
            {
                DataGridViewRow thisRow = dataGridView1.SelectedRows[0];
                DateTime logCreateDate;

                string logServerName = GetDataGridColumnValueAsString(thisRow.Index, "LogServerName");
                string logUserName = GetDataGridColumnValueAsString(thisRow.Index, "LogUserName");


                if (dataGridView1.Columns.Contains("LogCreateDate"))
                {
                    logCreateDate = (DateTime)thisRow.Cells["LogCreateDate"].Value;
                } else
                {
                    MessageBox.Show("LogCreateDate Column Missing");
                    return;
                }

                

                if (!dataGridView1.Columns.Contains("LogProperties"))
                {
                    MessageBox.Show("Requires LogProperties Column");
                    return;
                }

                // grab LogProperties column data as xml
                var xmlText = thisRow.Cells["LogProperties"].Value.ToString();

                // webbrowser Message doc Tab
                XmlBrowser m = (XmlBrowser)tabPage2.Controls["MsgBrowser"];
                m.DocumentText = GetHtmlFormattedView(xmlText, logCreateDate, logServerName, logUserName);

                // Entire XML Tab
                XmlDocument xDoc = new XmlDocument();
                try
                {
                    xDoc.LoadXml(xmlText);
                    XmlBrowser x = (XmlBrowser)tabPage3.Controls["XmlBrowser"];
                    x.DocumentXml = xDoc;
                    BindPropertyLogToListView(xmlText);
                } catch(XmlException xex)
                {
                    MessageBox.Show(xex.Message);
                }
            }
        }


        /// <summary>
        /// Get HTML Tab View for LogProperties XML
        /// </summary>
        /// <param name="xmlText"></param>
        /// <param name="logCreateDate"></param>
        /// <returns></returns>
        private string GetHtmlFormattedView(string xmlText, DateTime logCreateDate, string logServerName, string logUserName)
        {
            // setup sb and html doc
            StringBuilder sb = new StringBuilder();
            sb.Append("\n<style type=\"text/css\">h2 {color:blue; margin:0px 0px 0px 0px;} h3 {color:#615DFA} td { border-bottom:1px solid #dddddd;} table { width:100%; }\n"
                        + ".logBox { padding: 5px; background-color: #D2DEFC; border:1px solid #dadada; }"
                        +".logDate {font-size:90%; font-weight:bold;}"
                        +"</style>\n");
            XDocument x;

            try
            {
                x = XDocument.Parse(xmlText);
            }
            catch(XmlException xex)
            {
                MessageBox.Show(xex.Message);
                return null;
            }
            var propList = from p in x.Root.Elements("LogProperty")
                           select new
                                      {
                                          PropertyName = (string) p.Element("PropertyName"),
                                          PropertyValue = (string) p.Element("PropertyValue")
                                      };

            if (propList.Count()<1)
            {
                sb.Append("<h2>No Properties Found</h2>");
                return sb.ToString();
            }


            
            sb.AppendFormat("<div class=\"logBox\"><h2>Portal - [{0}] {1}</h2>\n<span class=\"logDate\">{2}</span>\n",
                            GetPropertyValueFromXml(xmlText, "PortalID"),
                            GetPropertyValueFromXml(xmlText, "PortalName"),
                            logCreateDate.ToString()
            );
            sb.AppendFormat("Server: {0}\tUser: {1}</div>", logServerName, logUserName);

            sb.AppendFormat("<h3>InnerException:</h2><p>{0}</p>", HttpUtility.HtmlEncode(GetPropertyValueFromXml(xmlText, "InnerException")));
            sb.AppendFormat("<h3>Message:</h2><p>{0}</p>", HttpUtility.HtmlEncode(GetPropertyValueFromXml(xmlText, "Message")));
            sb.Append("<h3>All Properties</h3>\n");
            sb.Append("\n<table border=\"0\" cellspacing=\"0\">\n");
            foreach (var prop in propList)
            {
                sb.AppendFormat("<tr><td>{0}</td><td>{1}</td><tr></tr>\n", 
                                    prop.PropertyName, 
                                    (prop.PropertyValue.Length>1)? HttpUtility.HtmlEncode(prop.PropertyValue):"&nbsp;");
            }
            sb.Append("\n</table>\n");
            return sb.ToString();
        }

        private void BindPropertyLogToListView(string propXml)
        {
            XDocument x = XDocument.Parse(propXml);
            var propList = from p in x.Root.Elements("LogProperty")
                           select new
                              {
                                  PropertyName = (string) p.Element("PropertyName"),
                                  PropertyValue = (string) p.Element("PropertyValue")
                              };

            // now bind to listview
            listView1.Items.Clear();
            foreach(var prop in propList)
            {
                string[] row = {prop.PropertyValue};
                listView1.Items.Add(prop.PropertyName).SubItems.AddRange(row);
            }
        }

        private string GetPropertyValueFromXml(string xmlstr, string propertyName)
        {
            try
            {
                // default xml with no C
                XDocument xDoc = XDocument.Parse(xmlstr);
                /* */
                var r = (from s in xDoc.Root.Elements("LogProperty")
                         where (string)s.Element("PropertyName") == propertyName
                         select new
                         {
                             InnerException = (string)s.Element("PropertyValue")
                         }).FirstOrDefault();

                return (r == null) ? string.Empty : r.InnerException;
            }
            catch { }
            return null;
        }

        private void listView1_Resize(object sender, EventArgs e)
        {
            listView1.Columns[1].Width = -1;
        }

        private void cntCopyValue_Opening(object sender, CancelEventArgs e)
        {

        }


        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Clipboard.SetData(DataFormats.Text, listView1.SelectedItems[0].Text);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Properties.Settings.Default.Save();
        }

        private void btnResetQuery_Click(object sender, EventArgs e)
        {
            string sql = "SELECT  TOP 20 LogTypeKey, LogCreateDate, LogServerName, LogProperties, LogEventID"
                         + " FROM EventLog"
                         + " ORDER BY LogCreateDate DESC";

            txtQuery.Text = sql;
        }

        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            int rowIndex = e.RowIndex;
            DataGridViewRow theRow = dataGridView1.Rows[rowIndex];
            DNNEventLogTypes.EventLogType eventLogKey= DNNEventLogTypes.EventLogType.NONE;
            string EventLogString = theRow.Cells["LogTypeKey"].Value.ToString();
            if (!string.IsNullOrEmpty(EventLogString))
            {
                eventLogKey = DNNEventLogTypes.EventLogType.NONE;

                try
                {
                    eventLogKey =
                        (DNNEventLogTypes.EventLogType) Enum.Parse(typeof (DNNEventLogTypes.EventLogType),
                                                                   theRow.Cells["LogTypeKey"].Value.ToString());
                }
                catch (Exception ex)
                {

                }

                if (!string.IsNullOrEmpty(EventLogString))
                {
                    Color bgc = Color.Blue;
                    Color fg = Color.White;

                    if (EventLogString.ToUpper().Contains("APPLICATION_"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        fg = Color.White;
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.GeneralAdminOperation));
                    }

                    if (EventLogString.ToUpper().Contains("LOGIN_SUPERUSER"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        fg = Color.White;
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.OperationSuccess));
                    }

                    if (EventLogString.ToUpper().Contains("HOST_ALERT"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        fg = Color.White;
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.HostAlert));
                    }

                    if (EventLogString.ToUpper().Contains("_FAILURE"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        fg = Color.White;
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.OperationFailure));
                    }


                    if (EventLogString.ToUpper().Contains("_DELETED"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        fg = Color.White;
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.ItemDeleted));
                    }


                    if (EventLogString.ToUpper().Contains("_UPDATED"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.ItemUpdated));
                    }

                    if (EventLogString.ToUpper().Contains("_CREATED"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.ItemCreated));
                    }

                    if (EventLogString.ToUpper().Contains("EXCEPTION"))
                    {
                        // Get Hexidecimal (html) value of enum color code value
                        bgc =
                           System.Drawing.ColorTranslator
                                         .FromHtml(DNNEventLogTypes
                                                      .GetHexStringColorCode(DNNEventLogTypes.DotNetNukeColorCodes.Exception) );
                    }

                    theRow.DefaultCellStyle.ForeColor = fg;
                    theRow.DefaultCellStyle.BackColor = bgc;
                } 

                // save cellstyle
                theRow.Tag = theRow.DefaultCellStyle;
            }

        }

        private void dataGridView1_RowLeave(object sender, DataGridViewCellEventArgs e)
        {
            int rowIndex = e.RowIndex;
            DataGridViewRow thisRow = dataGridView1.Rows[rowIndex];

            if (thisRow.Tag != null)
            {
                thisRow.DefaultCellStyle = (DataGridViewCellStyle)thisRow.Tag;
            }

        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {

        }

        /// <summary>
        /// Copy Log Data as Html (from web browser)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void copyAsHtmlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CopyCurrentLogItemToClipboard();
        }

        private void CopyCurrentLogItemToClipboard()
        {
            // Get Html from msg
            XmlBrowser m = (XmlBrowser)tabPage2.Controls["MsgBrowser"];
            Clipboard.SetText(m.DocumentText, TextDataFormat.Html);
            
            if (Clipboard.ContainsText(TextDataFormat.Html))
            {
                MessageBox.Show("Log Details copied to clipboard");
            }
            
        }
        
    }
}
